/* * Copyright 2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.rioproject.impl.jmx; import com.sun.tools.attach.VirtualMachine; import org.rioproject.config.Constants; import org.rioproject.net.HostUtil; import org.rioproject.rmi.RegistryUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.management.MBeanServer; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.remote.*; import java.io.File; import java.lang.management.ManagementFactory; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; /** * Provides JMX connection utilities. * * @author Dennis Reedy */ @SuppressWarnings("PMD.AvoidThrowingRawExceptionTypes") public class JMXConnectionUtil { static final Logger logger = LoggerFactory.getLogger(JMXConnectionUtil.class); /** * Create a {@link javax.management.remote.JMXConnectorServer}, bound to * the RMI Registry created by an infrastructure service (Cybernode or * Monitor). * * <p>If <tt>JMXConnectorServer</tt> has been created, return immediately. * If the <tt>JMXConnectorServer</tt> needs to be created, it will be * bound to the RMI Registry, and set the * <tt>org.rioproject.jmxServiceURL</tt> system property. * * <p>This utility uses the {@link org.rioproject.rmi.RegistryUtil} class to * obtain the port to access the RMI Registry. * * @throws Exception If there are errors reading the configuration, or * creating the {@link javax.management.remote.JMXConnectorServer} */ public static void createJMXConnection() throws Exception { if(System.getProperty(Constants.JMX_SERVICE_URL)!=null) return; RegistryUtil.checkRegistry(); String sPort = System.getProperty(Constants.REGISTRY_PORT, "0"); int registryPort = Integer.parseInt(sPort); if(registryPort==0) { logger.error("RMI Registry property [{}] not found, unable to create MBeanServer", Constants.REGISTRY_PORT); throw new Exception("Unable to create the JMXConnectorServer"); } MBeanServer mbs = MBeanServerFactory.getMBeanServer(); String hostAddress = HostUtil.getHostAddressFromProperty(Constants.RMI_HOST_ADDRESS); JMXServiceURL jmxServiceURL = new JMXServiceURL("service:jmx:rmi://"+hostAddress+":"+registryPort+ "/jndi/rmi://"+hostAddress+":"+registryPort+"/jmxrmi"); System.setProperty(Constants.JMX_SERVICE_URL, jmxServiceURL.toString()); if(logger.isInfoEnabled()) logger.info("JMXServiceURL={}", jmxServiceURL); Registry registry = LocateRegistry.getRegistry(registryPort); for(String s : registry.list()) { if(s.equals("jmxrmi")) { registry.unbind(s); } } JMXConnectorServer jmxConn = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, null, mbs); jmxConn.start(); if(logger.isDebugEnabled()) logger.debug("JMX Platform MBeanServer exported with RMI Connector"); } /** * Get the agentID of the Platform MBeanServer * * @return The agentID of the Platform MBeanServer * * @throws Exception if the agent ID cannot be found */ public static String getPlatformMBeanServerAgentId() throws Exception { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); final String SERVER_DELEGATE = "JMImplementation:type=MBeanServerDelegate"; final String MBEAN_SERVER_ID_KEY = "MBeanServerId"; ObjectName delegateObjName = new ObjectName(SERVER_DELEGATE); return (String) mbs.getAttribute(delegateObjName, MBEAN_SERVER_ID_KEY ); } /** * Using the <a * href="http://java.sun.com/javase/6/docs/technotes/guides/attach/index.html"> * JMX Attach API </a>, connect to a local Java Virtual Machine. * * <p>This utility requires Java 6 or greater. * * @param id The identifier used to connect to the Java Virtual Machine * @return An MBeanServerConnection to the platform MBeanServer of the * Java Virtual Machine identified, or null if the connection cannot be * created. * * @throws Exception if the following occurs: * <ul> * <li>MBeanServerConnection cannot be created</li> * <li>If the underlying provider either does not exist, or if the provider attempts to attach to a * Java virtual machine with which it is not compatible.</li> * <li>If an agent fails to initialize in the target Java virtual machine.</li> * <li>If an agent cannot be loaded into the target Java virtual machine.</li> * </ul> */ public static MBeanServerConnection attach(final String id) throws Exception { String jvmVersion = System.getProperty("java.version"); if(jvmVersion.contains("1.5")) { logger.info("The JMX Attach APIs require Java 6 or above. You are running Java {}", jvmVersion); return null; } VirtualMachine vm = VirtualMachine.attach(id); String connectorAddr = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); if (connectorAddr == null) { String agent = vm.getSystemProperties().getProperty("java.home")+File.separator+"lib"+File.separator+ "management-agent.jar"; vm.loadAgent(agent); connectorAddr = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); } MBeanServerConnection mbs = null; if(connectorAddr!=null) { JMXServiceURL serviceURL = new JMXServiceURL(connectorAddr); JMXConnector connector = JMXConnectorFactory.connect(serviceURL); mbs = connector.getMBeanServerConnection(); } return mbs; } }